package com.wiscamp.ninechapters.tags.adapter.resources;


import com.wiscamp.ninechapters.common.GlobalState;
import com.wiscamp.ninechapters.tags.application.dto.command.*;
import com.wiscamp.ninechapters.tags.application.dto.vo.EntityVO;
import com.wiscamp.ninechapters.tags.application.dto.vo.KnowledgePointVO;
import com.wiscamp.ninechapters.tags.application.dto.vo.TagNameVO;
import com.wiscamp.ninechapters.tags.application.services.EntityAppService;
import cube.ddd.adapter.BaseController;
import cube.ddd.adapter.RestResponse;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.aspect.HandleResourceException;
import cube.ddd.utils.ResourceUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.core.Context;
import org.springframework.web.bind.annotation.*;

import java.util.Collection;

/**
 * 应用实体服务端点
 *
 * @author yifeng
 */
@RestController
@RequestMapping("/api/Tags")
@Tag(name = "标签知识点-应用实体信息")
public class EntityController extends BaseController {
    private final EntityAppService entityAppService;

    public EntityController(EntityAppService entityAppService) {
        this.entityAppService = entityAppService;
    }

    //region entity

    /**
     * 通过编号获取应用实体
     *
     * @param entityId 应用实体编号
     * @return 应用实体VO
     */
    @GetMapping("Entities/{entityId}")
    @Operation(summary = "通过编号获取应用实体")
    @HandleResourceException
    public RestResponse<EntityVO> getEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                            @PathVariable("entityId") long entityId) {
        return ResourceUtils.getById(request, response, entityId, entityAppService::getEntity);
    }

    /**
     * 通过应用编号获取应用实体列表
     *
     * @param appId 应用编号
     * @return 应用实体VO列表
     */
    @GetMapping("Applications/{appId}/Entities")
    @Operation(summary = "通过应用编号获取应用实体列表")
    @HandleResourceException
    public RestResponse<Collection<EntityVO>> getEntities(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                          @PathVariable("appId") long appId) {
        return ResourceUtils.getListById(request, response, appId, entityAppService::getEntitiesByApplication);
    }

    /**
     * 通过应用编号和代码获取应用实体
     *
     * @param appId      应用编号
     * @param entityCode 应用实体代码
     * @return 应用实体VO
     */
    @GetMapping("Applications/{appId}/Entities/Code/{entityCode}")
    @Operation(summary = "通过应用编号和代码获取应用实体")
    @HandleResourceException
    public RestResponse<EntityVO> getEntityByCode(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                  @PathVariable("appId") long appId, @PathVariable("entityCode") String entityCode) {
        return ResourceUtils.getByTextAndId(request, response, entityCode, appId, entityAppService::getEntityByCode);
    }


    /**
     * 通过应用编号和应用实体名称获取应用实体列表
     *
     * @param appId      应用编号
     * @param entityName 应用实体名称
     * @return
     */
    @GetMapping("Applications/{appId}/Entities/Name/{entityName}")
    @Operation(summary = "通过应用编号和实体名称获取应用实体列表")
    @HandleResourceException
    public RestResponse<Collection<EntityVO>> getEntitiesByName(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                @PathVariable("appId") long appId, @PathVariable("entityName") String entityName) {
        return ResourceUtils.getListByTextAndId(request, response, entityName, appId, entityAppService::getEntitiesByName);
    }

    /**
     * 通过编号删除应用实体
     *
     * @param entityId 应用实体编号
     * @return 删除操作成功标志
     */
    @PutMapping("Entities/Actions/Delete")
    @Operation(summary = "通过编号删除应用实体")
    @HandleResourceException
    public RestResponse<Boolean> deleteEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                              @RequestBody DeleteCommand command) {
        return ResourceUtils.delete(request, response, command, entityAppService::deleteEntity);
    }

    @PutMapping("Entities/Actions/Enable")
    @Operation(summary = "启用应用实体")
    @HandleResourceException
    public RestResponse<Boolean> enableEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                              @RequestBody EnableCommand command) {
        return ResourceUtils.enable(request, response, command, entityAppService::enableEntity);
    }

    @PutMapping("Entities/Actions/Disable")
    @Operation(summary = "禁用应用实体")
    @HandleResourceException
    public RestResponse<Boolean> disableEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                               @RequestBody DisableCommand command) {
        return ResourceUtils.disable(request, response, command, entityAppService::disableEntity);
    }

    /**
     * 创建应用实体
     *
     * @param command 创建应用实体的命令对象
     * @return 应用实体VO
     */
    @PostMapping("Entities")
    @Operation(summary = "创建应用实体")
    @HandleResourceException
    public RestResponse<EntityVO> createEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                               @RequestBody CreateEntityCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, entityAppService::createEntity);
    }

    /**
     * 更新应用实体
     *
     * @param command 更新应用实体的命令对象
     * @return 应用实体VO
     */
    @PutMapping("Entities")
    @Operation(summary = "更新应用实体")
    @HandleResourceException
    public RestResponse<EntityVO> updateEntity(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                               @RequestBody UpdateEntityCommand command) {
        return ResourceUtils.createOrUpdate(request, response, command, entityAppService::updateEntity);
    }

    //endregion


    // region entityTag

    /**
     * 设置应用实体与标签关联
     *
     * @param command
     * @return
     */
    @PostMapping("Entities/Actions/Bind/Tag")
    @Operation(summary = "设置应用实体与标签关联")
    @HandleResourceException
    public RestResponse<Boolean> bindTag(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                         @RequestBody BindTagCommand command) {
        var success = entityAppService.bindTag(command);
        return ResourceUtils.getOkResponse(request, response, success);
    }

    /**
     * 取消应用实体与标签关联
     *
     * @param command
     * @return
     */
    @DeleteMapping("Entities/Actions/Unbind/Tag")
    @Operation(summary = "取消应用实体与标签关联")
    @HandleResourceException
    public RestResponse<Boolean> unbindTag(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                           @RequestBody UnbindTagCommand command) {
        var success = entityAppService.unbindTag(command);
        return ResourceUtils.getOkResponse(request, response, success);
    }

    /**
     * 通过应用编号应用实体编号和实例主键编号获取标签列表
     *
     * @param appId
     * @param entityCode
     * @param primaryKeyId
     * @return
     */
    @GetMapping("Applications/{appId}/Entities/{entityCode}/PrimaryKeys/{primaryKeyId}/Tags")
    @Operation(summary = "通过应用编号应用实体编号和实例主键编号获取标签列表")
    @HandleResourceException
    public RestResponse<Collection<TagNameVO>> getTagNamesByPrimaryKey(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                       @PathVariable("appId") long appId, @PathVariable("entityCode") String entityCode,
                                                                       @PathVariable("primaryKeyId") long primaryKeyId) {
        var tags = entityAppService.getTagNamesByPrimaryKey(appId, entityCode, primaryKeyId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    @GetMapping("Problems/{problemId}/TagNames")
    @Operation(summary = "通过问题编号获取标签列表")
    @HandleResourceException
    public RestResponse<Collection<TagNameVO>> getTagNamesByProblem(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                       @PathVariable("problemId") long problemId) {
        var tags = entityAppService.getTagNamesByProblem(GlobalState.APPLICATION_ID, problemId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    @GetMapping("KnowledgePoints/{pointId}/TagNames")
    @Operation(summary = "通过知识点编号获取标签列表")
    @HandleResourceException
    public RestResponse<Collection<TagNameVO>> getTagNamesByKnowledgePoint(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                           @PathVariable("pointId") long pointId) {
        var tags = entityAppService.getTagNamesByKnowledgePoint(GlobalState.APPLICATION_ID, pointId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    // endregion


    // region entityPoint

    /**
     * 设置应用实体与知识点关联
     *
     * @param command
     * @return
     */
    @PostMapping("Entities/Actions/Bind/KnowledgePoint")
    @Operation(summary = "设置应用实体与知识点关联")
    @HandleResourceException
    public RestResponse<Boolean> bindKnowledgePoint(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                    @RequestBody BindKnowledgePointCommand command) {
        var success = entityAppService.bindKnowledgePoint(command);
        return ResourceUtils.getOkResponse(request, response, success);
    }

    /**
     * 取消应用实体与知识点关联
     *
     * @param entity
     * @return
     */
    @DeleteMapping("Entities/Actions/Unbind/KnowledgePoint")
    @Operation(summary = "取消应用实体与知识点关联")
    @HandleResourceException
    public RestResponse<Boolean> unbindKnowledgePoint(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                      @RequestBody UnbindKnowledgePointCommand command) {
        var success = entityAppService.unbindKnowledgePoint(command);
        return ResourceUtils.getOkResponse(request, response, success);
    }

    @GetMapping("Problems/{problemId}/KnowledgePoints")
    @Operation(summary = "通过问题编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getKnowledgePointsByProblem(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                    @PathVariable("problemId") long problemId) {
        var tags = entityAppService.getKnowledgePointsByProblem(GlobalState.APPLICATION_ID, problemId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    @GetMapping("Problems/{problemId}/KnowledgePoints/Primary")
    @Operation(summary = "通过问题编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getPrimaryKnowledgePointsByProblem(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                                  @PathVariable("problemId") long problemId) {
        var tags = entityAppService.getPrimaryKnowledgePointsByProblem(GlobalState.APPLICATION_ID, problemId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    @GetMapping("Problems/{problemId}/KnowledgePoints/Minor")
    @Operation(summary = "通过问题编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getMinorKnowledgePointsByPrimaryKey(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                                         @PathVariable("problemId") long problemId) {
        var tags = entityAppService.getMinorKnowledgePointsByPrimaryKey(GlobalState.APPLICATION_ID, problemId);
        return ResourceUtils.getOkResponse(request, response, tags);
    }

    /**
     * 通过应用编号应用实体编号和实例主键编号获取知识点列表
     *
     * @param appId
     * @param entityCode
     * @param primaryKeyId
     * @return
     */
    @GetMapping("Applications/{appId}/Entities/{entityCode}/PrimaryKeys/{primaryKeyId}/KnowledgePoints")
    @Operation(summary = "通过应用编号应用实体编号和实例主键编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getKnowledgePointsByPrimaryKey(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                                     @PathVariable("appId") long appId,
                                                                                     @PathVariable("entityCode") String entityCode,
                                                                                     @PathVariable("primaryKeyId") long primaryKeyId) {
        var points = entityAppService.getKnowledgePointsByPrimaryKey(appId, entityCode, primaryKeyId);
        return ResourceUtils.getOkResponse(request, response, points);
    }

    @GetMapping("Applications/{appId}/Entities/{entityCode}/PrimaryKeys/{primaryKeyId}/KnowledgePoints/Primary")
    @Operation(summary = "通过应用编号应用实体编号和实例主键编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getPrimaryKnowledgePoints(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                                @PathVariable("appId") long appId,
                                                                                @PathVariable("entityCode") String entityCode,
                                                                                @PathVariable("primaryKeyId") long primaryKeyId) {
        var points = entityAppService.getKnowledgePointsByPrimaryKey(appId, entityCode, primaryKeyId, true);
        return ResourceUtils.getOkResponse(request, response, points);
    }

    @GetMapping("Applications/{appId}/Entities/{entityCode}/PrimaryKeys/{primaryKeyId}/KnowledgePoints/Minor")
    @Operation(summary = "通过应用编号应用实体编号和实例主键编号获取知识点列表")
    @HandleResourceException
    public RestResponse<Collection<KnowledgePointVO>> getMinorKnowledgePoints(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                                              @PathVariable("appId") long appId,
                                                                              @PathVariable("entityCode") String entityCode,
                                                                              @PathVariable("primaryKeyId") long primaryKeyId) {
        var points = entityAppService.getKnowledgePointsByPrimaryKey(appId, entityCode, primaryKeyId, false);
        return ResourceUtils.getOkResponse(request, response, points);
    }

    @GetMapping("Applications/{appId}/Entities/{entityCode}/Bind/KnowledgePoints/{pointId}/Quantity")
    @Operation(summary = "通过应用编号应用实体编号和知识点编号获取关联实体数量")
    @HandleResourceException
    public RestResponse<Long> countPrimaryKeyIdsByPoint(@Context HttpServletRequest request, @Context HttpServletResponse response,
                                                        @PathVariable("appId") long appId,
                                                        @PathVariable("entityCode") String entityCode,
                                                        @PathVariable("pointId") long pointId) {
        var quantity = entityAppService.countPrimaryKeyIdsByPoint(appId, entityCode, pointId);
        return ResourceUtils.getOkResponse(request, response, quantity);
    }
    // endregion
}
